/**
 * Copyright (C) 2013 Bohan
 *
 * This file is part of the Java SACNR API.
 *
 * Java SACNR API is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Java SACNR API is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package bohan.sacnr.api;

import bohan.sacnr.exception.ItemNotFoundException;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.IOException;
import java.net.MalformedURLException;

/**
 * This class does not decode HTML entities, you will have to do it yourself
 * @author Bohan
 */
public final class Business
{

    private final int businessID, security, stock;
    private final long updated;
    private final String name, owner, value, bank, location;
    private final String[] lastOwnerVisit, employees;
    private final float[] coordinates;

    public Business(int businessID) throws IOException
    {
        this.businessID = businessID;
        String data;
        try
        {
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(new URL("http://www.sacnr.com/business/"
                    + businessID).openStream()));
            StringBuilder sb = new StringBuilder(5000);
            while ((data = in.readLine()) != null)
                sb.append(data);
            in.close();
            updated = System.currentTimeMillis();
            data = sb.toString();
        } catch (MalformedURLException e)
        {
            /**
             * This exception should not occur, but in case it does, re-wrap it
             * and throw as a RunTimeException
             */
            throw new RuntimeException("MalformedURLException: " + e.getMessage(), e);
        }

        if (data.indexOf("<h2>Welcome to SACNR.com!</h2>") >= 0)
            throw new ItemNotFoundException("The business with id " + businessID
                    + " was not found.");
        int index;
        if ((index = data.indexOf("<h2>") + 4) >= 4)
            name = data.substring(index, data.indexOf('<', index));
        else
            throw new IllegalArgumentException(Player.EXCEPTION_MESSAGE);

        if ((index = data.indexOf("Owner:</th><td><a href=", index) + 23) < 23)
            throw new IllegalArgumentException(Player.EXCEPTION_MESSAGE);
        index = data.indexOf('>', index) + 1;
        owner = data.substring(index, data.indexOf('<', index));

        if ((index = data.indexOf("Last owner visit:</th><td>", index) + 26) >= 26)
        {
            lastOwnerVisit = new String[2];
            int secondIndex = data.indexOf('<', index);
            lastOwnerVisit[0] = data.substring(index, secondIndex);
            index = secondIndex + 7;
            lastOwnerVisit[1] = data.substring(index, data.indexOf(')', index));
        }
        else
            throw new IllegalArgumentException(Player.EXCEPTION_MESSAGE);

        if ((index = data.indexOf("Value:</th><td>", index) + 15) >= 15)
            value = data.substring(index, data.indexOf('<', index));
        else
            throw new IllegalArgumentException(Player.EXCEPTION_MESSAGE);

        if ((index = data.indexOf("Security:</th><td>", index)) < 0)
            throw new IllegalArgumentException(Player.EXCEPTION_MESSAGE);
        int i = 0;
        while ((index = data.indexOf("/icon/shield.png", index) + 16) >= 16)
            i++;
        security = i;

        if ((index = data.indexOf("Bank:</th><td>", index) + 14) >= 14)
            bank = data.substring(index, data.indexOf('<', index));
        else
            throw new IllegalArgumentException(Player.EXCEPTION_MESSAGE);

        if ((index = data.indexOf("Stock:</th><td>", index) + 15) >= 15)
            try
            {
                stock = Integer.parseInt(data.substring(index, data.indexOf('<', index)));
            } catch (Exception e)
            {
                throw new IllegalArgumentException(Player.EXCEPTION_MESSAGE);
            }
        else
            throw new IllegalArgumentException(Player.EXCEPTION_MESSAGE);

        if ((index = data.indexOf("Employees (", index)) >= 0)
        {
            ArrayList<String> list = new ArrayList<String>();
            index = data.indexOf('>', data.indexOf("<a href=\"http://www.sacnr.com/u/", index)) + 1;
            while (index >= 1)
            {
                list.add(data.substring(index, data.indexOf("<", index)));
                int secondIndex = data.indexOf("<a href=\"http://www.sacnr.com/u/", index);
                if (secondIndex < 0)
                    break;
                index = data.indexOf('>', secondIndex) + 1;
            }
            employees = list.toArray(new String[0]);
        }
        else
            throw new IllegalArgumentException(Player.EXCEPTION_MESSAGE);

        if ((index = data.indexOf("Map location (", index) + 14) >= 14)
            location = data.substring(index, data.indexOf(')', index));
        else
            throw new IllegalArgumentException(Player.EXCEPTION_MESSAGE);

        if ((index = data.indexOf("src=\"http://www.sacnr.com/map/", index) + 30) >= 30)
        {
            coordinates = new float[2];
            int secondIndex = data.indexOf('/', index);
            coordinates[0] = Float.parseFloat(data.substring(index, secondIndex));
            index = secondIndex + 1;
            coordinates[1] = Float.parseFloat(data.substring(index, data.indexOf('/', index)));
        }
        else
            throw new IllegalArgumentException(Player.EXCEPTION_MESSAGE);
    }

    /**
     * 
     * @return The time since this business's data was last updated in 
     * milliseconds
     */
    public long getAge()
    {
        return System.currentTimeMillis() - this.updated;
    }

    public String getName()
    {
        return this.name;
    }
    
    public int getBusinessID()
    {
        return this.businessID;
    }

    public String getOwner()
    {
        return this.owner;
    }

    /**
     * 
     * @return String array of size 2. index 0 represents the physically date & 
     * time that the owner last visited his business, index 1 represents how 
     * long has it been since the last visit.
     */
    public String[] getLastOwnerVisit()
    {
        return this.lastOwnerVisit;
    }

    public String getValue()
    {
        return this.value;
    }

    public int getSecurity()
    {
        return this.security;
    }

    public String getBank()
    {
        return this.bank;
    }

    public int getStock()
    {
        return this.stock;
    }

    public String[] getEmployees()
    {
        return this.employees;
    }

    public String getLocation()
    {
        return this.location;
    }

    public float[] getCoordinates()
    {
        return this.coordinates;
    }
    
    /**
     * Creates a new instance of <code>Business</code> object with updated
     * business stats *EXPENSIVE*.
     * <p>
     * Note that since <code>Business</code> is an immutable class, this method 
     * does not update the current <code>Business</code> instance, but returns
     * a new updated instance of a <code>Business</code> object. 
     * <p>
     * Note that this method is always expensive, as it connects to the sacnr 
     * website to update the business's stats.
     * @return An up to date <code>Business</code> object.
     * @throws IOException Thrown from the <code>Business</code> constructor
     * when it can't connect to the server.
     * @see Business#Business(int) 
     */
    public Business update() throws IOException
    {
        return new Business(businessID);
    }
}
